package com.zlp.mall.modules.pms.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zlp.mall.common.api.Pager;
import com.zlp.mall.common.api.RespCode;
import com.zlp.mall.common.exception.ApiException;
import com.zlp.mall.common.exception.CustomException;
import com.zlp.mall.common.util.BeanToUtils;
import com.zlp.mall.common.util.MethodUtil;
import com.zlp.mall.modules.cms.model.PrefrenceArea;
import com.zlp.mall.modules.cms.model.PrefrenceAreaProductRelation;
import com.zlp.mall.modules.cms.model.SubjectProductRelation;
import com.zlp.mall.modules.cms.service.PrefrenceAreaProductRelationService;
import com.zlp.mall.modules.cms.service.SubjectProductRelationService;
import com.zlp.mall.modules.pms.dto.req.ProductAddReq;
import com.zlp.mall.modules.pms.dto.req.ProductQueryReq;
import com.zlp.mall.modules.pms.dto.req.ProductUpdReq;
import com.zlp.mall.modules.pms.dto.resp.ProductCategoryResp;
import com.zlp.mall.modules.pms.dto.resp.ProductResp;
import com.zlp.mall.modules.pms.dto.resp.ProductUpdInfoResp;
import com.zlp.mall.modules.pms.mapper.ProductMapper;
import com.zlp.mall.modules.pms.model.*;
import com.zlp.mall.modules.pms.service.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 商品信息 服务实现类
 * </p>
 *
 * @author ZouLiPing
 * @since 2021-09-23
 */
@Service
@RequiredArgsConstructor
@Slf4j(topic = "ProductServiceImpl")
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements ProductService {

    @Resource
    private ProductCategoryService productCategoryService;
    private final MemberPriceService memberPriceService;
    private final ProductLadderService productLadderService;
    private final ProductFullReductionService productFullReductionService;
    private final SkuStockService skuStockService;
    private final ProductAttributeValueService productAttributeValueService;
    private final SubjectProductRelationService subjectProductRelationService;
    private final PrefrenceAreaProductRelationService prefrenceAreaProductRelationService;
    private final ProductVertifyRecordService productVertifyRecordService;

    @Override
    public Pager<ProductResp> list(ProductQueryReq productQueryReq) {

        log.info("list.req productQueryReq={}", JSON.toJSONString(productQueryReq));
        Page pages = new Page(productQueryReq.getPageNum(), productQueryReq.getPageSize());
        LambdaQueryWrapper<Product> lambdaWrapper = new LambdaQueryWrapper<>();
        // 商品名称
        if (StrUtil.isNotBlank(productQueryReq.getKeyword())) {
            lambdaWrapper.like(Product::getName, productQueryReq.getKeyword());
        }
        // 商品货号
        if (!StrUtil.isBlank(productQueryReq.getProductSn())) {
            lambdaWrapper.eq(Product::getProductSn, productQueryReq.getProductSn());
        }

        // 商品分类
        if (productQueryReq.getProductCategoryId() != null && productQueryReq.getProductCategoryId() > 0) {
            lambdaWrapper.eq(Product::getProductCategoryId, productQueryReq.getProductCategoryId());
        }
        // 商品品牌
        if (productQueryReq.getBrandId() != null && productQueryReq.getBrandId() > 0) {
            lambdaWrapper.eq(Product::getBrandId, productQueryReq.getBrandId());
        }
        // 上架状态
        if (productQueryReq.getPublishStatus() != null) {
            lambdaWrapper.eq(Product::getPublishStatus, productQueryReq.getPublishStatus());
        }
        // 审核状态
        if (productQueryReq.getVerifyStatus() != null) {
            lambdaWrapper.eq(Product::getVerifyStatus, productQueryReq.getVerifyStatus());
        }
        lambdaWrapper.orderByAsc(Product::getSort)
                .orderByDesc(Product::getId);
        Page page = this.page(pages, lambdaWrapper);
        List records = page.getRecords();
        if (CollectionUtils.isNotEmpty(page.getRecords())) {
            List<ProductResp> productResps = BeanToUtils.entityToList(records, ProductResp.class);
            return new Pager(productResps, page.getTotal(), productQueryReq.getPageSize(), productQueryReq.getPageNum());
        }
        return new Pager<>();
    }

    @Override
    public ProductResp getProductDetail(Long id) {

        log.info("getProductDetail.req id={}", id);
        Product product = this.getById(id);
        if (Objects.isNull(product)) {
            throw new CustomException(RespCode.BACK_PMS_3000, MethodUtil.getLineInfo());
        }
        return BeanToUtils.doToDto(product, ProductResp.class);
    }

    @Override
    public List<Product> getProductByBrandId(Long id) {

        log.info("getProductByBrandId.req id={}", id);
        LambdaQueryWrapper<Product> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Product::getBrandId, id);
        return this.list(queryWrapper);
    }

    @Override
    public boolean updateByBrandId(Long brandId, String name) {

        log.info("updateByBrandId.req brandId={}", brandId);
        LambdaUpdateWrapper<Product> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.
                eq(Product::getBrandId, brandId).
                ne(Product::getBrandName, name).
                set(Product::getBrandName, name);
        return this.update(updateWrapper);
    }


    @Override
    public List<Product> getProductByCategoryIds(List<Long> categoryIds) {

        log.info("getProductByCategoryId.req categoryIds={}", categoryIds);
        LambdaQueryWrapper<Product> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(Product::getProductCategoryId, categoryIds);
        return this.list(queryWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean create(ProductAddReq productAddReq) {

        log.info("create.req productAddReq={}", JSON.toJSONString(productAddReq));
        //创建商品
        Product product = BeanToUtils.dtoToDo(productAddReq, Product.class);
        product.setId(null);
        this.save(product);
        //根据促销类型设置价格：会员价格、阶梯价格、满减价格
        Long productId = product.getId();
        //会员价格
        relateAndInsertList(memberPriceService, productAddReq.getMemberPriceList(), productId);
        //阶梯价格
        relateAndInsertList(productLadderService, productAddReq.getProductLadderList(), productId);
        //满减价格
        relateAndInsertList(productFullReductionService, productAddReq.getProductFullReductionList(), productId);
        //处理 sku 的编码
        handleSkuStockCode(productAddReq.getSkuStockList(), productId);
        //添加sku库存信息
        relateAndInsertList(skuStockService, productAddReq.getSkuStockList(), productId);
        //添加商品参数,添加自定义商品规格
        relateAndInsertList(productAttributeValueService, productAddReq.getProductAttributeValueList(), productId);
        //关联专题
        relateAndInsertList(subjectProductRelationService, productAddReq.getSubjectProductRelationList(), productId);
        //关联优选
        relateAndInsertList(prefrenceAreaProductRelationService, productAddReq.getPrefrenceAreaProductRelationList(), productId);
        return Boolean.TRUE;
    }

    @Override
    public boolean updateDeleteStatus(List<Long> ids, Integer deleteStatus) {

        log.info("updateDeleteStatus.req ids={},deleteStatus={}", ids, deleteStatus);
        if (CollectionUtil.isEmpty(ids)) {
            return Boolean.FALSE;
        }
        this.removeByIds(ids);
        return Boolean.TRUE;
    }

    @Override
    public List<ProductResp> simpleList(String keyword) {

        log.info("simpleList.req keyword={}", keyword);
        LambdaQueryWrapper<Product> queryWrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isNotBlank(keyword)) {
            queryWrapper.like(Product::getName, keyword).or()
                    .like(Product::getProductSn, keyword);
        }
        List<Product> productList = this.list(queryWrapper);
        return BeanToUtils.entityToList(productList, ProductResp.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateVerifyStatus(List<Long> ids, Integer verifyStatus, String detail) {

        log.info("updateVerifyStatus.req ids={},verifyStatus={},detail={}", ids, verifyStatus, detail);
        if (CollectionUtil.isEmpty(ids)) {
            return false;
        }
        updateProductSatus(ids, verifyStatus, 4);

        //修改完审核状态后插入审核记录
        List<ProductVertifyRecord> list = new ArrayList<>();
        for (Long id : ids) {
            ProductVertifyRecord record = new ProductVertifyRecord();
            record.setProductId(id);
            record.setDetail(detail);
            record.setStatus(verifyStatus);
            record.setVertifyMan("test");
            list.add(record);
        }
        productVertifyRecordService.saveBatch(list);
        return Boolean.TRUE;
    }

    @Override
    public boolean updatePublishStatus(List<Long> ids, Integer publishStatus) {

        log.info("updatePublishStatus.req ids={},publishStatus={}", ids, publishStatus);
        if (CollectionUtil.isEmpty(ids)) {
            return false;
        }
        updateProductSatus(ids, publishStatus, 1);
        return Boolean.TRUE;
    }

    @Override
    public boolean updateNewStatus(List<Long> ids, Integer newStatus) {

        log.info("updateNewStatus.req ids={},newStatus={}", ids, newStatus);
        if (CollectionUtil.isEmpty(ids)) {
            return false;
        }
        updateProductSatus(ids, newStatus, 2);
        return Boolean.TRUE;
    }

    @Override
    public boolean updateRecommendStatus(List<Long> ids, Integer recommendStatus) {

        log.info("updateRecommendStatus.req ids={},recommendStatus={}", ids, recommendStatus);
        if (CollectionUtil.isEmpty(ids)) {
            return false;
        }
        updateProductSatus(ids, recommendStatus, 3);
        return Boolean.TRUE;
    }

    @Override
    public ProductUpdInfoResp getUpdateInfo(Long productId) {

        log.info("getUpdateInfo.req productId={}", productId);
        Product product = this.getByProductId(productId);
        ProductUpdInfoResp productUpdInfoResp = BeanToUtils.doToDto(product, ProductUpdInfoResp.class);
        ProductCategoryResp productCategory = productCategoryService.getInfoById(product.getProductCategoryId());
        productUpdInfoResp.setCateParentId(productCategory.getParentId());
        // 阶梯价格
        List<ProductLadder> productLadderList = productLadderService.getByProductId(productId);
        productUpdInfoResp.setProductLadderList(productLadderList);
        // 满减价格
        List<ProductFullReduction> fullReductionList = productFullReductionService.getByProductId(productId);
        productUpdInfoResp.setProductFullReductionList(fullReductionList);
        // 会员价格
        List<MemberPrice> memberPriceList = memberPriceService.getByProductId(productId);
        productUpdInfoResp.setMemberPriceList(memberPriceList);
        // 商品 SKU
        List<SkuStock> skuStockList = skuStockService.getByProductId(productId);
        productUpdInfoResp.setSkuStockList(skuStockList);
        // 商品属性值
        List<ProductAttributeValue> productAttributeValueList = productAttributeValueService.getByProductId(productId);
        productUpdInfoResp.setProductAttributeValueList(productAttributeValueList);
        return productUpdInfoResp;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean update(Long id, ProductUpdReq productUpdReq) {

        log.info("update.req id={},productUpdReq={}", id, JSON.toJSONString(productUpdReq));
        this.getByProductId(id);
        Product product = BeanToUtils.dtoToDo(productUpdReq, Product.class);
        product.setId(id);
        this.updateById(product);
        //会员价格
        LambdaQueryWrapper<MemberPrice> memberQueryWrapper = new LambdaQueryWrapper<>();
        memberQueryWrapper.eq(MemberPrice::getProductId, id);
        memberPriceService.remove(memberQueryWrapper);
        relateAndInsertList(memberPriceService, productUpdReq.getMemberPriceList(), id);
        //阶梯价格
        LambdaQueryWrapper<ProductLadder> ladderQueryWrapper = new LambdaQueryWrapper();
        ladderQueryWrapper.eq(ProductLadder::getProductId, id);
        productLadderService.remove(ladderQueryWrapper);
        relateAndInsertList(productLadderService, productUpdReq.getProductLadderList(), id);
        //满减价格
        LambdaQueryWrapper<ProductFullReduction> fullQueryWrapper = new LambdaQueryWrapper();
        fullQueryWrapper.eq(ProductFullReduction::getProductId, id);
        productFullReductionService.remove(fullQueryWrapper);
        relateAndInsertList(productFullReductionService, productUpdReq.getProductFullReductionList(), id);
        //修改sku库存信息
        handleUpdateSkuStockList(id, productUpdReq);
        //修改商品参数,添加自定义商品规格
        LambdaQueryWrapper<ProductAttributeValue> productAttributeValueWrapper = new LambdaQueryWrapper();
        productAttributeValueWrapper.eq(ProductAttributeValue::getProductId, id);
        productAttributeValueService.remove(productAttributeValueWrapper);
        relateAndInsertList(productAttributeValueService, productUpdReq.getProductAttributeValueList(), id);

        //关联专题
        LambdaQueryWrapper<SubjectProductRelation> subjectProductRelationWrapper = new LambdaQueryWrapper();
        subjectProductRelationWrapper.eq(SubjectProductRelation::getProductId, id);
        subjectProductRelationService.remove(subjectProductRelationWrapper);
        relateAndInsertList(subjectProductRelationService, productUpdReq.getSubjectProductRelationList(), id);
        //关联优选
        LambdaQueryWrapper<PrefrenceAreaProductRelation> prefrenceAreaWrapper = new LambdaQueryWrapper();
        prefrenceAreaWrapper.eq(PrefrenceAreaProductRelation::getProductId, id);
        prefrenceAreaProductRelationService.remove(prefrenceAreaWrapper);
        relateAndInsertList(prefrenceAreaProductRelationService, productUpdReq.getPrefrenceAreaProductRelationList(), id);
        return Boolean.TRUE;
    }

    public void handleUpdateSkuStockList(Long id, ProductUpdReq productUpdReq) {

        //当前的sku信息
        List<SkuStock> currSkuList = productUpdReq.getSkuStockList();
        //当前没有sku直接删除
        if (CollUtil.isEmpty(currSkuList)) {
            LambdaQueryWrapper<SkuStock> skuStockQueryWrapper = new LambdaQueryWrapper<>();
            skuStockQueryWrapper.eq(SkuStock::getProductId, id);
            skuStockService.remove(skuStockQueryWrapper);
            return;
        }
        //获取初始sku信息
        LambdaQueryWrapper<SkuStock> skuStockQueryWrapper = new LambdaQueryWrapper<>();
        skuStockQueryWrapper.eq(SkuStock::getProductId, id);
        List<SkuStock> oriStuList = skuStockService.list(skuStockQueryWrapper);

        //获取新增sku信息
        List<SkuStock> insertSkuList = currSkuList.stream().filter(item -> item.getId() == null).collect(Collectors.toList());
        //获取需要更新的sku 信息
        List<SkuStock> updateSkuList = currSkuList.stream().filter(item -> item.getId() != null).collect(Collectors.toList());

        List<Long> updateSkuIds = updateSkuList.stream().map(SkuStock::getId).collect(Collectors.toList());
        //获取需要删除的sku信息
        List<SkuStock> removeSkuList = oriStuList.stream().filter(item -> !updateSkuIds.contains(item.getId())).collect(Collectors.toList());
        handleSkuStockCode(insertSkuList, id);
        handleSkuStockCode(updateSkuList, id);
        //新增sku
        if (CollUtil.isNotEmpty(insertSkuList)) {
            relateAndInsertList(skuStockService, insertSkuList, id);
        }
        //删除 sku
        if (CollUtil.isNotEmpty(removeSkuList)) {
            List<Long> removeSkuIds = removeSkuList.stream().map(SkuStock::getId).collect(Collectors.toList());
            LambdaQueryWrapper<SkuStock> stockQueryWrapper = new LambdaQueryWrapper<>();
            stockQueryWrapper.in(SkuStock::getId, removeSkuIds);
            skuStockService.remove(skuStockQueryWrapper);
        }

        //修改sku
        if (CollUtil.isNotEmpty(updateSkuList)) {
            for (SkuStock pmsSkuStock : updateSkuList) {
                skuStockService.updateById(pmsSkuStock);
            }
        }
    }

    @Override
    public Product getByProductId(Long productId) {

        log.info("getByProductId.req productId={}", productId);
        Product product = this.getById(productId);
        if (Objects.isNull(product)) {
            throw new CustomException(RespCode.BACK_PMS_3000, MethodUtil.getLineInfo());
        }
        return product;
    }

    /**
     * 更新商品状态值
     *
     * @param ids
     * @param status
     * @param type
     * @date: 2021/10/11 16:12
     * @return: void
     */
    private void updateProductSatus(List<Long> ids, Integer status, int type) {

        for (Long id : ids) {
            LambdaUpdateWrapper<Product> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(Product::getId, id);
            if (Objects.equals(type, 1)) {
                updateWrapper.set(Product::getPublishStatus, status);
            } else if (Objects.equals(type, 2)) {
                updateWrapper.set(Product::getNewStatus, status);
            } else if (Objects.equals(type, 3)) {
                updateWrapper.set(Product::getRecommandStatus, status);
            } else if (Objects.equals(type, 4)) {
                updateWrapper.set(Product::getVerifyStatus, status);
            }
            this.update(updateWrapper);
        }
    }

    /**
     * 公共方法： 保存会员价格、阶梯价格、减满价格、 sku 、 spu 商品的关联数据
     * 统一： 都需要设置商品id,  都需要批量保存
     *
     * @param service   可以操作的 service
     * @param dataList  要插入的数据
     * @param productId 建立关系的id
     */
    private void relateAndInsertList(IService service, List dataList, Long productId) {
        try {
            if (CollectionUtil.isEmpty(dataList)) return;
            for (Object item : dataList) {
                Method setId = item.getClass().getMethod("setId", Long.class);
                setId.invoke(item, (Long) null);
                Method setProductId = item.getClass().getMethod("setProductId", Long.class);
                setProductId.invoke(item, productId);
            }
            service.saveBatch(dataList);
        } catch (Exception e) {
            log.error("创建产品出错:{}", e.getMessage());
            throw new ApiException(e.getMessage());
        }
    }


    /**
     * 处理 sku 的编码
     *
     * @param skuStockList
     * @param productId
     * @date: 2021/10/8 11:37
     */
    private void handleSkuStockCode(List<SkuStock> skuStockList, Long productId) {

        if (CollectionUtil.isEmpty(skuStockList)) return;

        for (int i = 0; i < skuStockList.size(); i++) {
            SkuStock skuStock = skuStockList.get(i);
            if (StringUtils.isEmpty(skuStock.getSkuCode())) {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
                StringBuffer sb = new StringBuffer();
                //日期
                sb.append(sdf.format(new Date()));
                //四位商品id
                sb.append(String.format("%04d", productId));
                //三位索引id
                sb.append(String.format("%03d", i + 1));
                skuStock.setSkuCode(sb.toString());
            }
        }
    }
}
